package org.shiro.demo.service.realm;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.shiro.demo.entity.Permission;
import org.shiro.demo.entity.Role;
import org.shiro.demo.entity.User;
import org.shiro.demo.service.IUserService;

/**
 * 
 * @author admin 在认证、授权内部实现机制中都有提到，最终处理都将交给Real进行处理。
 *         因为在Shiro中，最终是通过Realm来获取应用程序中的用户、角色及权限信息的。
 *         通常情况下，在Realm中会直接从我们的数据源中获取Shiro需要的验证信息。 可以说，Realm是专用于安全框架的DAO. (重要)
 */
public class ShiroDbRealm extends AuthorizingRealm
{

	@Resource(name = "userService")
	private IUserService userService;

	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals)
	{

		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		// 获取当前登录的用户名
		String account = (String) super.getAvailablePrincipal(principals);

		List<String> roles = new ArrayList<String>();
		List<String> permissions = new ArrayList<String>();
		User user = userService.getByAccount(account);
		if (user != null)
		{
			// 查看用户都有哪些角色，角色都有哪些权限，一一遍历
			if (user.getRoles() != null && user.getRoles().size() > 0)
			{
				for (Role role : user.getRoles())
				{
					roles.add(role.getName());
					if (role.getPermissions() != null && role.getPermissions().size()>0)
					{
						for (Permission permission : role.getPermissions())
						{
							if (!StringUtils.isEmpty(permission.getPermission()))
							{
								permissions.add(permission.getPermission());
							}
						}
					}
				}
			}
		} else
		{
			throw new AuthorizationException();
		}
		// 给当前用户设置角色
		info.addRoles(roles);
		// 给当前用户设置权限
		info.addStringPermissions(permissions);
		return info;

	}

	/**
	 * Shiro的认证过程最终会交由Realm执行，这时会调用Realm的getAuthenticationInfo(token)方法。
	 * 认证回调函数,登录时调用.
	 */
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authcToken) throws AuthenticationException
	{
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		User user = userService.getByAccount(token.getUsername());
		if (user != null)
		{
			return new SimpleAuthenticationInfo(user.getAccount(),
					user.getPassword(), user.getNickname());
		} else
		{
			return null;
		}
	}
}
